use std::fmt::Display;

use clap::{builder::PossibleValue, ValueEnum};
use tabled::{settings::Style as TableStyle, Table, Tabled};

/// The style of the output.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Style {
    Human,
    Machine,
}

impl Display for Style {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::Human => write!(f, "human"),
            Self::Machine => write!(f, "machine"),
        }
    }
}

impl ValueEnum for Style {
    fn value_variants<'a>() -> &'a [Self] {
        &[Self::Human, Self::Machine]
    }

    fn to_possible_value(&self) -> Option<PossibleValue> {
        match self {
            Self::Human => Some(PossibleValue::new("human")),
            Self::Machine => Some(PossibleValue::new("machine")),
        }
    }

    fn from_str(input: &str, ignore_case: bool) -> Result<Self, String> {
        let input = if ignore_case {
            input.to_lowercase()
        } else {
            input.to_string()
        };
        match input.as_str() {
            "human" => Ok(Self::Human),
            "machine" => Ok(Self::Machine),
            _ => Err(format!("Unknown style: {}", input)),
        }
    }
}

/// Visualizes the data in a table.
pub fn visualize<I, T>(style: Style, data: I)
where
    I: IntoIterator<Item = T>,
    T: Tabled,
{
    let mut table = Table::new(data);
    let table = if style == Style::Human {
        table.with(TableStyle::rounded())
    } else {
        table.with(TableStyle::empty())
    };

    println!("{}", table);
}
